package gpl.pierrick.brihaye.aramorph;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Logger;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

/**
 * This classes holds data for one dictionary.
 * @author Ahmed Saad, 2005
 */
public class InMemoryDictionary implements Dictionary{
	/**A logger to write log messages*/
	private static Logger logger = Logger.getLogger(InMemoryDictionary.class.getName());

	/**Tells whether the dictionary normlized or not*/
	private boolean dictionaryNormalized;
	
	/**A map that stores all dictionary entries. Each unvocalized entry maps to many dictionary entries*/
	private Map<String,Collection<DictionaryEntry>> unvocalized2Entries = new LinkedHashMap<String,Collection<DictionaryEntry>>();
	
	/**A map that gives all dictionary entries for each gloss*/
	private Map<String,Collection<DictionaryEntry>> gloss2Entries = new LinkedHashMap<String,Collection<DictionaryEntry>>();
	
	public InMemoryDictionary(boolean normalized) {
		dictionaryNormalized = normalized;
	}

	public boolean isDictionaryNormalized() {
		return dictionaryNormalized;
	}

	public void setDictionaryNormalized(boolean dictionaryNormalized) {
		this.dictionaryNormalized = dictionaryNormalized;
	}

	/**Adds a dictionary entry to this dictionary*/
	public void addDictionaryEntry(DictionaryEntry de) {
		Collection<DictionaryEntry> collection;
		//add to unvocalized2Entries
		collection = unvocalized2Entries.get(de.getEntry(dictionaryNormalized));
		if (collection == null) {
			collection = new ArrayList<DictionaryEntry>();
			unvocalized2Entries.put(de.getEntry(dictionaryNormalized),collection);
		}
		collection.add(de);
		//add to gloss2Entries
		for (String gloss : de.getGlosses()) {
			collection = gloss2Entries.get(gloss);
			if (collection == null) {
				collection = new ArrayList<DictionaryEntry>();
				gloss2Entries.put(gloss,collection);
			}
			collection.add(de);
		}
	}
	
	public boolean contains(String entry) {
		return unvocalized2Entries.containsKey(entry);
	}
	
	public Iterator<DictionaryEntry> getIterator(String entry) {
		Collection<DictionaryEntry> collection = unvocalized2Entries.get(entry);
		return collection!=null?collection.iterator():null;
	}

	public Iterator<DictionaryEntry> getIteratorForGloss(String gloss) {
		Collection<DictionaryEntry> collection = gloss2Entries.get(gloss);
		return collection!=null?collection.iterator():null;
	}

	/**
	 * Loads a dictionary from an XML file.
	 * The file is already open and its input stream is passed.
	 * @param is the input stream for the XML file.
	 * @return the dictionary that has been loaded.
	 */
	public void loadFromXML(InputStream is) {
		SAXParserFactory factory = SAXParserFactory.newInstance();
		factory.setValidating(false);
		try {
			SAXParser sax = factory.newSAXParser();
			XMLDictionaryLoader dl = new XMLDictionaryLoader(this);
			sax.parse(is,dl);
			dl.writeStats();
		} catch (ParserConfigurationException pce) {
			logger.warning("Could not create that parser.");
			logger.warning(pce.getMessage());
		} catch (SAXException se) {
			logger.warning("Problem with the SAX parser");
			logger.warning(se.getMessage());
		} catch (IOException ioe) {
			logger.warning("Error reading file.");
			logger.warning(ioe.getMessage());
		}
	}
}
